#include <string.h>
#include "ktota.h"
#include "ktota_slave.h"


#if 1
	#define ota_dbg  printf
#else
	#define dbg(...)  do{}while(0)
#endif

static uint8_t remain_buf[3], remain_len=0;	/* 发送方无法保证4字节对齐时需要用到 */

static uint8_t ktota_slave_clear_flashflag(void) {
//    bin_head *app_head= (bin_head*)ADDR_FLASH_SECTOR_BAK;
//    if(0 != verify_app_head(app_head)){
//    	if(1 == verify_app_data((u8*)ADDR_FLASH_SECTOR_BAK)){
//    		
//    		printf("升级文件验证OK，5s后重启开始升级\r\n");
//    		write_restart_cmd(5);
//    		return;
//    	}
//    }
    return 1;
}

static uint8_t _ota_bak_sector_verify(void) {
//    bin_head *app_head= (bin_head*)ADDR_FLASH_SECTOR_BAK;
//    if(0 != verify_app_head(app_head)){
//    	if(1 == verify_app_data((u8*)ADDR_FLASH_SECTOR_BAK)){
//    		
//    		printf("升级文件验证OK，5s后重启开始升级\r\n");
//    		write_restart_cmd(5);
//    		return;
//    	}
//    }
    return 1;
}

static void _ota_msg_ack_rxlen(uint32_t total_rlen) {
    uint8_t buf[4] = {0};
    buf[0] = (uint8_t)(total_rlen&0xff);
    buf[1] = (uint8_t)((total_rlen >> 8)&0xff);
    buf[2] = (uint8_t)((total_rlen >> 16)&0xff);
    buf[3] = (uint8_t)(total_rlen >> 24);
    ota_msg_send(buf, 4);
}

static void _ota_write_flash(uint32_t addr_off, KTOTA_REGION *firmware, uint32_t total_rlen)
{
	uint32_t rlen, write_len, file_len;
	uint8_t *write_buf;
	file_len = firmware->file_len;
	rlen = firmware->data_len + remain_len;		//加上剩余的
	if( remain_len > 0 ) {
		ota_dbg("remain_len = %d", remain_len);
		write_buf= (uint8_t*)(firmware->flash_data) - remain_len;/* 占用头部的一部分 */
		(void)memcpy(write_buf, remain_buf, remain_len);
	} else {
		write_buf= (uint8_t*)firmware->flash_data;
	}
	if(total_rlen < firmware->file_len) {
		remain_len= rlen%4;	//还没有收完，计算剩余长度	
		write_len=  rlen/4;
	} else {
		remain_len=0;
		write_len=  (rlen+3)/4;
	}
	ota_flash_write(addr_off, (uint32_t*)write_buf, write_len);
	_ota_msg_ack_rxlen(total_rlen); /* 通知主机本次接收成功 */
	ota_dbg("ack len:%d\r\n", total_rlen);		
	if( total_rlen >= firmware->file_len ){
		ota_dbg("ota文件接收成功%d/%d\r\n", total_rlen, firmware->file_len);
        if( _ota_bak_sector_verify() ) {
            ota_dbg("ota文件校验成功\r\n");
        }else {
            ota_dbg("ota文件校验失败\r\n");
        }
	}
}

void ktota_slave_msg_handle(uint8_t *msg_buf, uint32_t msg_len)
{
	static uint32_t ack_len = 0;
    static uint16_t erase_flag = 0;
	uint32_t rlen = msg_len, addr_off = 0, crcval = 0;
	KTOTA_REGION *firmware = (KTOTA_REGION*)msg_buf;
    ota_dbg(" model %08x version %08x\r\n",firmware->model, firmware->version );
    if(firmware->model != BOARD_MODEL || rlen <= KTOTA_HEAD_LEN) {
        _ota_msg_ack_rxlen(OTAMSGERR_MODEL); /* 通知主机产品号错误 */
        ota_dbg("model don't match %x %x\r\n", firmware->model, BOARD_MODEL);
    }else if(firmware->version <= SOFT_VERSION) {
        _ota_msg_ack_rxlen(OTAMSGERR_VERSION); /* 通知主机版本号错误 */
        ota_dbg("version don't match %x %x\r\n", firmware->version, SOFT_VERSION);
    }else {
        rlen-= KTOTA_HEAD_LEN;
		if( rlen != firmware->data_len ) {
			ota_dbg("rec len err, %d / %d \r\n",rlen, firmware->data_len);
			return;
		}
		crcval = ota_calcrc32((const uint8_t*)firmware->flash_data, rlen);
		if( crcval == firmware->crc32val ) {
			if( firmware->region_idx == 0 ) { /* 第一帧 */
				ack_len = 0;
				remain_len = 0;
                if( 0 == erase_flag ) {
                    if( ota_flash_erase() ) {
                    _ota_msg_ack_rxlen(OTAMSGERR_OTHER); /* 通知主机错误 */
                    ota_dbg("ota flash erase faild\r\n");
                        return;
    				}else {
    				    ota_dbg("ota flash erase success\r\n");
                    }
                    erase_flag = 100; /* 擦写成功与否都认为已擦的 */
                }else {
                    erase_flag--; /* 如反复收到握手，再次擦写 */
                }
			}
			else if( firmware->region_idx != ack_len ) {
				ota_dbg("ota msg warning: recv %d, pend %d \r\n",firmware->region_idx, ack_len);
				return;
			}
			/* 等价于 write_addr = OTA_BASE + (ack_len/4)*4; */	
			addr_off = ack_len&0xFFFFFFFC;	
			ack_len+= rlen;
			_ota_write_flash(addr_off, firmware, ack_len);
		}else {
            ota_dbg("ota slave crc err: %08x / %08x\r\n", crcval, firmware->crc32val);
        }
    }
}





